package com.pjc.rpc;

import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TMultiplexedProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pjc.rpc.pool.ThriftPoolObjectFacory;
import com.pjc.rpc.pool.ThriftScoketProvider;
import com.pjc.thrift.TInnerProto;
import com.pjc.thrift.TLogicService;

/**
 * 接入逻辑服务器调用类
 * 
 * @author 王畅
 * @version 创建时间：2015-6-16 上午09:21:28
 */
public class LogicRpc {

	private static final Logger log = LoggerFactory.getLogger(LogicRpc.class);

	private static LogicRpc instance;

	private ThriftScoketProvider poolProvider;

	public static LogicRpc getInstance() {
		if (instance == null) {
			synchronized (LogicRpc.class) {
				if (instance == null) {
					instance = new LogicRpc();
				}
			}
		}
		return instance;
	}

	/**
	 * 初始化thrift客户端
	 * 
	 * @author 王畅
	 * @param host
	 * @param port
	 * @param timeOut
	 * @param maxTotal
	 * @param maxIdle
	 * @throws Exception
	 */
	public void init(String host, int port, int timeOut, int maxTotal, int maxIdle) throws Exception {
		ThriftPoolObjectFacory factory = new ThriftPoolObjectFacory();
		factory.init(host, port, timeOut);
		poolProvider = new ThriftScoketProvider();
		poolProvider.init(factory, maxTotal, maxIdle);
	}

	/**
	 * 发送消息到逻辑服务器
	 * 
	 * @author 王畅
	 * @param data
	 * @return
	 */
	public int send(TInnerProto data) {
		TSocket socket = null;
		try {
			socket = poolProvider.getConnection();
			int result = send(socket, data, 0);
			return result;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			if (socket != null)
				poolProvider.invalidate(socket);
			return 1;
		}

	}

	/**
	 * 发送消息到逻辑服务器(次数)
	 * 
	 * @author 王畅
	 * @param socket
	 * @param data
	 * @param times
	 * @return
	 * @throws Exception
	 */
	private int send(TSocket socket, TInnerProto data, int times) throws Exception {
		try {
			TTransport transport = new TFramedTransport(socket);
			TProtocol protocol = new TCompactProtocol(transport);
			TMultiplexedProtocol mpl = new TMultiplexedProtocol(protocol, "logicService");
			TLogicService.Client client = new TLogicService.Client(mpl);
			int result = client.sendData(data);
			poolProvider.returnConn(socket);
			return result;
		} catch (Exception e) {
			if (times > 3) {
				return 1;
			}
			times++;
			poolProvider.invalidate(socket);
			socket = poolProvider.getConnection();
			return send(socket, data, times);
		}
	}

	/**
	 * 关闭
	 * 
	 * @author 王畅
	 */
	public void close() {
		poolProvider.closePool();
	}

}
